package com.campus.schedule.timer;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.campus.common.bean.common.Resp;
import com.campus.common.enums.OrderStatusEnum;
import com.campus.common.exception.BusinessException;
import com.campus.schedule.entity.*;
import com.campus.schedule.feign.ProfitSharingFeignClient;
import com.campus.schedule.feign.ProfitSharingFeignClient.ProfitSharingRequestDTO;
import com.campus.schedule.feign.ProfitSharingFeignClient.ProfitSharingResponseDTO;
import com.campus.schedule.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 订单分账定时任务服务
 *
 * @author ZhaoYuJie
 * @since 2025-01-15
 */
@Service
@Slf4j
public class OrderProfitSharingScheduleService {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderProfitSharingService orderProfitSharingService;

    @Autowired
    private OrderProfitSharingDetailService orderProfitSharingDetailService;

    @Autowired
    private ProfitSharingFeignClient profitSharingFeignClient;

    @Autowired
    private DeliveryService deliveryService;

    @Autowired
    private DeliveryUserService deliveryUserService;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Value("${wechat.appid}")
    private String appId;

    @Value("${wechat.pay.merchant-id}")
    private String platformMerchantId;

    @Value("${wechat.pay.merchant-name}")
    private String platformMerchantName;

    /**
     * 每天凌晨2点执行分账任务
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void executeOrderProfitSharing() {
        log.info("开始执行订单分账定时任务");
        
        try {
            int totalProcessed = 0;
            int batchCount = 0;
            
            while (true) {
                // 查询需要分账的订单（每次最多100条）
                List<Order> ordersToSettle = getOrdersToSettle();
                
                if (ordersToSettle.isEmpty()) {
                    log.info("第{}批次：没有需要分账的订单，分账任务结束", batchCount + 1);
                    break;
                }
                
                batchCount++;
                log.info("第{}批次：找到 {} 个需要分账的订单", batchCount, ordersToSettle.size());
                
                // 处理当前批次的订单分账
                int currentBatchProcessed = 0;
                for (Order order : ordersToSettle) {
                    // 为每个订单创建独立的事务
                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                    TransactionStatus status = transactionManager.getTransaction(def);
                    
                    try {
                        processOrderProfitSharing(order);
                        // 提交事务
                        transactionManager.commit(status);
                        currentBatchProcessed++;
                        totalProcessed++;
                        log.info("订单分账处理成功，订单ID：{}", order.getId());
                    } catch (Exception e) {
                        // 回滚当前订单的事务
                        transactionManager.rollback(status);
                        log.error("处理订单分账失败，订单ID：{}，已回滚事务", order.getId(), e);
                    }
                }
                
                log.info("第{}批次处理完成：成功处理{}个订单，累计处理{}个订单", 
                        batchCount, currentBatchProcessed, totalProcessed);
                
                // 如果当前批次处理的订单数少于100，说明已经处理完所有订单
                if (ordersToSettle.size() < 100) {
                    log.info("当前批次订单数少于100条，分账任务结束");
                    break;
                }
            }
            
            log.info("订单分账定时任务执行完成，共处理{}批次，累计处理{}个订单", batchCount, totalProcessed);
        } catch (Exception e) {
            log.error("执行订单分账定时任务异常", e);
        }
    }

    /**
     * 查询需要分账的订单
     * 条件：status=4（已完成）且finish_time是今天以前且profit_settled=0（未结算）
     */
    private List<Order> getOrdersToSettle() {
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getStatus, OrderStatusEnum.COMPLETED.getValue()) // 已完成
                .lt(Order::getFinishTime, todayStart) // 完成时间早于今天凌晨
                .eq(Order::getProfitSettled, 0) // 未结算
                .last("LIMIT 100"); // 最多100条
        
        return orderService.list(queryWrapper);
    }

    /**
     * 处理单个订单的分账
     */
    public void processOrderProfitSharing(Order order) {
        log.info("开始处理订单分账，订单ID：{}，配送员分账：{}，平台分账：{}", 
                order.getId(), order.getDeliveryProfit(), order.getPlatformProfit());
        
        try {
            // 1. 添加分账接收方（配送员和平台服务商商户号）
            boolean deliveryAdded = true;
            boolean platformAdded = true;
            
            // 添加配送员分账接收方
            if (order.getDeliveryId() != null && order.getDeliveryProfit() != null && 
                order.getDeliveryProfit().compareTo(BigDecimal.ZERO) > 0) {
                deliveryAdded = addDeliveryReceiver(order);
            }
            
            // 添加平台分账接收方
            if (order.getPlatformProfit() != null && order.getPlatformProfit().compareTo(BigDecimal.ZERO) > 0) {
                platformAdded = addPlatformReceiver(order);
            }
            
            if (!deliveryAdded || !platformAdded) {
                log.error("添加分账接收方失败，订单ID: {}，配送员: {}，平台: {}", 
                        order.getId(), deliveryAdded, platformAdded);
                return;
            }

            // 获取子商户号
            String subMchid = getSubMchid(order.getMerchantId());
            if (subMchid == null) {
                throw new RuntimeException("获取子商户号失败，商户ID: " + order.getMerchantId());
            }

            // 2. 先保存分账记录，获取主键ID作为outOrderNo
            OrderProfitSharing profitSharing = new OrderProfitSharing();
            profitSharing.setOrderId(order.getId());
            profitSharing.setSubMchid(subMchid);
            profitSharing.setState("PROCESSING"); // 处理中状态
            profitSharing.setCreateTime(LocalDateTime.now());
            orderProfitSharingService.save(profitSharing);
            
            // 3. 构建分账请求（使用订单表中的分账金额和分账记录ID）
            ProfitSharingRequestDTO request = buildProfitSharingRequest(order, subMchid, profitSharing.getId());

            //如果分账接收方为空，则不需要调用分账API
            if (request.getReceivers().isEmpty()) {
                log.info("订单分账接收方为空，订单ID：{}", order.getId());
                profitSharing.setState("FINISHED");
                orderProfitSharingService.updateById(profitSharing);

            }else{
                log.info("开始调用分账API，订单ID：{}", order.getId());
                // 4. 调用分账API
                Resp<ProfitSharingResponseDTO> result = profitSharingFeignClient.createProfitSharing(request);

                if (!"0".equals(result.getCode()) || result.getData() == null) {
                    log.error("调用分账API失败，订单ID：{}，错误信息：{}", order.getId(), result.getMessage());
                    throw new BusinessException("调用分账API失败，订单ID：" + order.getId());
                }

                ProfitSharingResponseDTO response = result.getData();

                // 5. 更新分账记录
                updateProfitSharingRecords(profitSharing, response);

                log.info("订单分账处理成功，订单ID：{}，微信分账单号：{}", order.getId(), response.getOrderId());
            }

            // 6. 更新订单状态
            order.setProfitSettled(1);
            orderService.updateById(order);
        } catch (Exception e) {
            log.error("处理订单分账异常，订单ID：{}", order.getId(), e);
            throw e;
        }
    }



    /**
     * 添加配送员分账接收方
     */
    private boolean addDeliveryReceiver(Order order) {
        try {
            String deliveryCustomerOpenId = getDeliveryCustomerOpenId(order.getDeliveryId());
            if (deliveryCustomerOpenId == null) {
                log.error("获取配送员顾客端OpenID失败，配送员ID: {}", order.getDeliveryId());
                return false;
            }
            
            // 获取子商户号
            String subMchid = getSubMchid(order.getMerchantId());
            if (subMchid == null) {
                log.error("获取子商户号失败，商户ID: {}", order.getMerchantId());
                return false;
            }
            
            Resp<Boolean> result = profitSharingFeignClient.addReceiver(
                    subMchid,
                    "PERSONAL_OPENID",
                    deliveryCustomerOpenId,
                    null,
                    "STAFF"
            );
            
            if ("0".equals(result.getCode()) && Boolean.TRUE.equals(result.getData())) {
                log.info("配送员分账接收方添加成功，配送员ID: {}", order.getDeliveryId());
                return true;
            } else {
                log.error("配送员分账接收方添加失败，配送员ID: {}，错误信息: {}", 
                        order.getDeliveryId(), result.getMessage());
                return false;
            }
        } catch (Exception e) {
            log.error("添加配送员分账接收方异常，配送员ID: {}", order.getDeliveryId(), e);
            return false;
        }
    }
    
    /**
     * 添加平台分账接收方
     */
    private boolean addPlatformReceiver(Order order) {
        try {
            // 获取子商户号
            String subMchid = getSubMchid(order.getMerchantId());
            if (subMchid == null) {
                log.error("获取子商户号失败，商户ID: {}", order.getMerchantId());
                return false;
            }
            
            Resp<Boolean> result = profitSharingFeignClient.addReceiver(
                    subMchid,
                    "MERCHANT_ID",
                    platformMerchantId,
                    platformMerchantName,
                    "SERVICE_PROVIDER"
            );
            
            if ("0".equals(result.getCode()) && Boolean.TRUE.equals(result.getData())) {
                log.info("平台分账接收方添加成功，平台商户号: {}", platformMerchantId);
                return true;
            } else {
                log.error("平台分账接收方添加失败，平台商户号: {}，错误信息: {}", 
                        platformMerchantId, result.getMessage());
                return false;
            }
        } catch (Exception e) {
            log.error("添加平台分账接收方异常，平台商户号: {}", platformMerchantId, e);
            return false;
        }
    }

    /**
     * 构建分账请求
     */
    private ProfitSharingRequestDTO buildProfitSharingRequest(Order order, String subMchid, Long profitSharingId) {
        ProfitSharingRequestDTO request = new ProfitSharingRequestDTO();
        
        request.setSubMchid(subMchid);
        request.setAppid(this.appId);
        request.setTransactionId(order.getTransactionId());
        request.setOutOrderNo(profitSharingId.toString()); // 使用分账记录主键ID作为outOrderNo
        request.setUnfreezeUnsplit(true); // 解冻剩余未分资金
        
        // 构建分账接收方列表
        List<ProfitSharingRequestDTO.ReceiverDTO> receivers = new ArrayList<>();
        
        // 配送员分账（使用订单表中的deliveryProfit字段）
        if (order.getDeliveryId() != null && order.getDeliveryProfit() != null && 
            order.getDeliveryProfit().compareTo(BigDecimal.ZERO) > 0) {
            String deliveryOpenId = getDeliveryCustomerOpenId(order.getDeliveryId());
            if (deliveryOpenId != null) {
                ProfitSharingRequestDTO.ReceiverDTO deliveryReceiver = new ProfitSharingRequestDTO.ReceiverDTO();
                deliveryReceiver.setType("PERSONAL_OPENID");
                deliveryReceiver.setAccount(deliveryOpenId);
                deliveryReceiver.setAmount(order.getDeliveryProfit().multiply(new BigDecimal("100")).intValue());
                deliveryReceiver.setDescription("配送员收益分账");
                receivers.add(deliveryReceiver);
            }
        }
        
        // 平台分账（使用订单表中的platformProfit字段，分账给服务商商户号）
        if (order.getPlatformProfit() != null && order.getPlatformProfit().compareTo(BigDecimal.ZERO) > 0) {
            ProfitSharingRequestDTO.ReceiverDTO platformReceiver = new ProfitSharingRequestDTO.ReceiverDTO();
            platformReceiver.setType("MERCHANT_ID");
            platformReceiver.setAccount(platformMerchantId); // 从配置文件读取服务商商户号
            platformReceiver.setAmount(order.getPlatformProfit().multiply(new BigDecimal("100")).intValue());
            platformReceiver.setDescription("平台收益分账");
            receivers.add(platformReceiver);
        }
        
        request.setReceivers(receivers);
        return request;
    }
    
    /**
     * 获取子商户号
     */
    private String getSubMchid(Integer merchantId) {
        try {
            Merchant merchant = merchantService.getById(merchantId);
            if (merchant != null) {
                return merchant.getSubMchid();
            }
            log.error("未找到商户信息，商户ID: {}", merchantId);
            return null;
        } catch (Exception e) {
            log.error("获取子商户号异常，商户ID: {}", merchantId, e);
            return null;
        }
    }
    


    /**
     * 更新分账记录
     */
    private void updateProfitSharingRecords(OrderProfitSharing profitSharing, ProfitSharingResponseDTO response) {
        // 更新分账主记录
        profitSharing.setWechatOrderId(response.getOrderId());
        profitSharing.setState(response.getState());
        profitSharing.setTransactionId(response.getTransactionId());
        profitSharing.setUpdateTime(LocalDateTime.now());
        orderProfitSharingService.updateById(profitSharing);
        
        // 保存分账记录
        if (response.getReceivers() != null) {
            for (ProfitSharingResponseDTO.ReceiverDetailDTO receiver : response.getReceivers()) {
                OrderProfitSharingDetail detail = new OrderProfitSharingDetail();
                detail.setSharingId(profitSharing.getId());
                detail.setAmount(receiver.getAmount());
                detail.setDescription(receiver.getDescription());
                detail.setType(receiver.getType());
                detail.setAccount(receiver.getAccount());
                detail.setResult(receiver.getResult());
                detail.setFailReason(receiver.getFailReason());
                detail.setDetailId(receiver.getDetailId());
                detail.setCreateTime(LocalDateTime.now());
                orderProfitSharingDetailService.save(detail);
            }
        }
        
        log.info("分账记录更新成功，订单ID：{}，分账记录ID：{}，配送员分账：{}元，平台分账：{}元", 
                profitSharing.getOrderId(), profitSharing.getId(), 
                response.getReceivers() != null && response.getReceivers().size() > 0 ? "已处理" : "无", 
                response.getReceivers() != null && response.getReceivers().size() > 1 ? "已处理" : "无");
    }

    /**
     * 每天凌晨4点执行分账结果查询任务
     */
    @Scheduled(cron = "0 0 4 * * ?")
    public void queryProfitSharingResults() {
        log.info("开始执行分账结果查询定时任务");
        
        try {
            int totalProcessed = 0;
            int batchCount = 0;
            
            while (true) {
                // 查询处理中的分账记录（每次最多100条）
                List<OrderProfitSharing> processingRecords = getProcessingProfitSharingRecords();
                
                if (processingRecords.isEmpty()) {
                    log.info("第{}批次：没有处理中的分账记录，查询任务结束", batchCount + 1);
                    break;
                }
                
                batchCount++;
                log.info("第{}批次：找到 {} 个处理中的分账记录", batchCount, processingRecords.size());
                
                // 处理当前批次的分账记录
                int currentBatchProcessed = 0;
                for (OrderProfitSharing profitSharing : processingRecords) {
                    // 为每个分账记录创建独立的事务
                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                    TransactionStatus status = transactionManager.getTransaction(def);
                    
                    try {
                        queryAndUpdateProfitSharingResult(profitSharing);
                        // 提交事务
                        transactionManager.commit(status);
                        currentBatchProcessed++;
                        totalProcessed++;
                        log.info("分账结果查询更新成功，分账记录ID：{}", profitSharing.getId());
                    } catch (Exception e) {
                        // 回滚当前分账记录的事务
                        transactionManager.rollback(status);
                        log.error("查询分账结果失败，分账记录ID：{}，已回滚事务", profitSharing.getId(), e);
                    }
                }
                
                log.info("第{}批次处理完成：成功处理{}个分账记录，累计处理{}个分账记录", 
                        batchCount, currentBatchProcessed, totalProcessed);
                
                // 如果当前批次处理的记录数少于100，说明已经处理完所有记录
                if (processingRecords.size() < 100) {
                    log.info("当前批次分账记录数少于100条，查询任务结束");
                    break;
                }
            }
            
            log.info("分账结果查询定时任务执行完成，共处理{}批次，累计处理{}个分账记录", batchCount, totalProcessed);
        } catch (Exception e) {
            log.error("执行分账结果查询定时任务异常", e);
        }
    }
    
    /**
     * 查询处理中的分账记录
     * 条件：state=PROCESSING
     */
    private List<OrderProfitSharing> getProcessingProfitSharingRecords() {
        LambdaQueryWrapper<OrderProfitSharing> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderProfitSharing::getState, "PROCESSING")
                .isNotNull(OrderProfitSharing::getTransactionId)
                .last("LIMIT 100"); // 最多100条
        
        return orderProfitSharingService.list(queryWrapper);
    }
    
    /**
     * 查询并更新分账结果
     */
    public void queryAndUpdateProfitSharingResult(OrderProfitSharing profitSharing) {
        log.info("开始查询分账结果，分账记录ID：{}，订单ID：{}", 
                profitSharing.getId(), profitSharing.getOrderId());
        
        try {
            // 调用查询分账结果API
            Resp<ProfitSharingResponseDTO> result = profitSharingFeignClient.queryProfitSharing(
                    profitSharing.getSubMchid(),
                    profitSharing.getTransactionId(),
                    profitSharing.getId().toString()
            );
            
            if (!"0".equals(result.getCode()) || result.getData() == null) {
                log.error("查询分账结果API失败，分账记录ID：{}，错误信息：{}", 
                        profitSharing.getId(), result.getMessage());
                return;
            }
            
            ProfitSharingResponseDTO response = result.getData();
            
            // 更新分账主记录状态
            profitSharing.setState(response.getState());
            profitSharing.setUpdateTime(LocalDateTime.now());
            orderProfitSharingService.updateById(profitSharing);
            
            // 更新分账明细记录
            if (response.getReceivers() != null) {
                for (ProfitSharingResponseDTO.ReceiverDetailDTO receiver : response.getReceivers()) {
                    if (receiver.getDetailId() != null) {
                        // 根据detailId查询分账明细记录
                        LambdaQueryWrapper<OrderProfitSharingDetail> detailQuery = new LambdaQueryWrapper<>();
                        detailQuery.eq(OrderProfitSharingDetail::getDetailId, receiver.getDetailId());
                        
                        OrderProfitSharingDetail detail = orderProfitSharingDetailService.getOne(detailQuery);
                        if (detail != null) {
                            // 更新分账结果和失败原因
                            detail.setResult(receiver.getResult());
                            detail.setFailReason(receiver.getFailReason());
                            orderProfitSharingDetailService.updateById(detail);
                            
                            log.info("更新分账明细成功，明细ID：{}，结果：{}，失败原因：{}", 
                                    detail.getId(), receiver.getResult(), receiver.getFailReason());
                        } else {
                            log.warn("未找到对应的分账明细记录，detailId：{}", receiver.getDetailId());
                        }
                    }
                }
            }
            
            log.info("分账结果查询更新成功，分账记录ID：{}，状态：{}", 
                    profitSharing.getId(), response.getState());
        } catch (Exception e) {
            log.error("查询分账结果异常，分账记录ID：{}", profitSharing.getId(), e);
            throw e;
        }
    }

    /**
     * 根据配送员ID获取配送员在顾客端的OpenID
     * 通过配送员ID查询Delivery表，再通过deliveryUserId查询DeliveryUser表获取customerOpenid
     */
    private String getDeliveryCustomerOpenId(Integer deliveryId) {
        try {
            // 1. 根据配送员ID查询Delivery表获取deliveryUserId
            Delivery delivery = deliveryService.getById(deliveryId);
            if (delivery == null || delivery.getDeliveryUserId() == null) {
                log.warn("配送员不存在或未关联用户，deliveryId: {}", deliveryId);
                return null;
            }
            
            // 2. 根据deliveryUserId查询DeliveryUser表获取customerOpenid
            DeliveryUser deliveryUser = deliveryUserService.getById(delivery.getDeliveryUserId());
            if (deliveryUser == null || deliveryUser.getCustomerOpenid() == null) {
                log.warn("配送员用户不存在或未绑定顾客端微信，deliveryUserId: {}", delivery.getDeliveryUserId());
                return null;
            }
            
            log.info("成功获取配送员在顾客端的OpenID，deliveryId: {}, deliveryUserId: {}, customerOpenid: {}",
                    deliveryId, delivery.getDeliveryUserId(), deliveryUser.getCustomerOpenid());
            return deliveryUser.getCustomerOpenid();
        } catch (Exception e) {
            log.error("获取配送员在顾客端的OpenID失败，deliveryId: {}", deliveryId, e);
            return null;
        }
    }
}